package czy.demo.service;


import czy.demo.pojo.Person;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class PersonService {


    private static Logger logger = LoggerFactory.getLogger(PersonService.class);
    private static Map<Integer,Person> persons = new HashMap<>();

    static{
        persons.put(1,new Person(1,"张三",23,new Date()));
        persons.put(2,new Person(2,"李四",24,new Date()));
        persons.put(3,new Person(3,"王五",25,new Date()));
    }

    /** 缓存有局限性，一般查询列表时，都无法缓存
     * 因为列表查询条件和缓存结果之间命中率太低
     * 甚至无法判断是否命中
     */
    public Map<Integer,Person> getAll(){
        return persons;
    }

    /**
     * cacheNames：缓存名称，相当于一个命名空间，最后存储key为person::1,一开始cacheNames并不会在redis中生成任何数据结构
     * 最后缓存的key为CacheKeyPrefix根据cacheNames生成的值加上这里的key
     * unless：如果spel表达式得到满足，那么结果不会被缓存，除非的意思
     */
    @Cacheable(cacheNames = {"person"},key="#id",unless="#result == null" )
    public Person get(Integer id){
        logger.info("调用service中的get方法一次");
        return persons.get(id);
    }

    /**
     * CachePut注解不会阻止方法执行，而是将方法返回值按照规则缓存起来
     * 一整套缓存机制中，key的生成方式应该统一
     * 一般创建、更新方法需要更新缓存
     */
    @CachePut(cacheNames = {"person"},key="#person.getId()")
    public Person create(Person person){
        logger.info("调用service中的create方法一次");
        persons.put(person.getId(),person);
        return person;
    }

    /**
     * 更新方法应该更新缓存值
     */
    @CachePut(cacheNames = {"person"},key="#person.getId()")
    public Person update(Person person){
        logger.info("调用service中的update方法一次");
        persons.put(person.getId(),person);
        return person;
    }

    /**
     * CacheEvict注解不会阻止方法执行，而是按照规则清除指定key的缓存
     * 一整套缓存规则中，key生成策略应该统一，而KeyGenerator一般满足不了这个要求、
     * 一般删除方法应该清除相应缓存
     */
    @CacheEvict(cacheNames = {"person"},key="#id")
    public void delete(Integer id){
        logger.info("调用service中的delete方法一次");
        persons.remove(id);
    }

}
